package com.fin.zw.aiqas.service;

import com.fin.zw.aiqas.entity.*;
import com.fin.zw.aiqas.enums.ReviewStatus;
import com.fin.zw.aiqas.enums.ReviewTaskStatus;
import com.fin.zw.aiqas.model.request.ReviewTaskRequest;
import com.fin.zw.aiqas.model.request.ReviewTaskToDetailRequest;
import com.fin.zw.aiqas.model.response.DepartmentResponse;
import com.fin.zw.aiqas.model.response.InspectionDetailQueryResponse;
import com.fin.zw.aiqas.model.response.ReviewTaskResponse;
import com.fin.zw.aiqas.model.session.SessionModel;
import com.fin.zw.aiqas.repository.*;
import com.fin.zw.aiqas.util.BadRequestException;
import com.google.common.collect.Sets;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Transient;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @Description: 复核任务Service
 * @Author: ZhangGQ
 * @Date: 2019/9/10 10:46
 */
@Service("reviewTaskService")
public class ReviewTaskService {
    private final static Logger logger = LoggerFactory.getLogger(ReviewTaskService.class);

    @Autowired
    private UserInfoRepository userInfoRepository;
    @Autowired
    private ReviewTaskRepository reviewTaskRepository;
    @Autowired
    private InspectionRepository inspectionRepository;
    @Autowired
    private InspectionDetailRepository inspectionDetailRepository;
    @Autowired
    private TaskInfoRepository taskInfoRepository;

    @Autowired
    @PersistenceContext
    private EntityManager entityManager;
    private JPAQueryFactory jpaQueryFactory;

    @PostConstruct
    public void init() {
        jpaQueryFactory = new JPAQueryFactory(entityManager);
    }


    /**
     * 添加
     * @param request
     * @param sessionModel
     */
    @Transient
    public void addReviewTask(ReviewTaskRequest request, SessionModel sessionModel) {
        Set<InspectionDetail> inspectionDetailSet = fetchMethod(request);
        //新建复核任务
        if (!request.getReviewUserIds().isEmpty()) {
            Iterator<UserInfo> iterator = userInfoRepository.findAll(QUserInfo.userInfo.id.in(request.getReviewUserIds())).iterator();
            Set<UserInfo> userInfoSet = Sets.newHashSet(iterator);
            ReviewTask reviewTask = new ReviewTask();
            reviewTask.setReviewTaskBatch(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
            reviewTask.setReviewTaskNum(inspectionDetailSet.size());
            reviewTask.setReviewTaskFinishNum(0);
            reviewTask.setReviewUserNum(userInfoSet.size());
            reviewTask.setReviewTaskStatus(ReviewTaskStatus.CHECKING);
            reviewTask.setCheckProp(request.getCheckProp());
            reviewTask.setTaskId(request.getTaskId());
            reviewTask.setTaskBatch(request.getTaskBatch());
            reviewTask.setServiceCode(request.getServiceCode());
            reviewTask.setAllotRule(request.getAllotRule());
            reviewTask.setUserInfoSet(userInfoSet);
            reviewTask.setCreateTime(new Date());
            reviewTask.setOperatorId(sessionModel.getUserId());
            reviewTask.setOperatorRealName(sessionModel.getUserName());
            ReviewTask save = reviewTaskRepository.save(reviewTask);
            //设置明细中的复核任务的ID
            Iterator<InspectionDetail> inspectionDetailIterator = inspectionDetailSet.iterator();
            Iterator<UserInfo> userInfoIterator = userInfoSet.iterator();
            while (inspectionDetailIterator.hasNext()) {
                InspectionDetail inspectionDetail = inspectionDetailIterator.next();
                inspectionDetail.setReviewTask(save);
                if (userInfoIterator.hasNext()) {
                    inspectionDetail.setReviewUserInfo(userInfoIterator.next());
                } else {
                    userInfoIterator = userInfoSet.iterator();
                    inspectionDetail.setReviewUserInfo(userInfoIterator.next());
                }
            }
            inspectionDetailRepository.saveAll(inspectionDetailSet);
            //修改质检结果表中的状态-已复核
            if (!inspectionDetailSet.isEmpty()) {
                InspectionDetail next = inspectionDetailSet.iterator().next();
                InspectionInfo inspectionInfo = inspectionRepository.findById(next.getInspectionInfo().getId()).orElseThrow(() -> new BadRequestException("", "修改质检结果时查询质检结果异常"));
                inspectionInfo.setStatus(ReviewStatus.HAVE_REVIEW);
                inspectionRepository.save(inspectionInfo);
            }
        } else {
            logger.error("未选择分配人员");
        }
    }

    /**
     * 查询对应的数量
     *
     * @param request
     */
    public Integer fetchNum(ReviewTaskRequest request) {
        Set<InspectionDetail> inspectionDetailSet = fetchMethod(request);
        return inspectionDetailSet.size();
    }

    /**
     * 上面两个查询公共代码
     *
     * @param request
     */
    private Set<InspectionDetail> fetchMethod(ReviewTaskRequest request) {
        //查询复核任务明细
        QInspectionDetail qInspectionDetail = QInspectionDetail.inspectionDetail;
        BooleanBuilder builder = new BooleanBuilder();
        //只要质检结果中未复核的数据
        builder.and(qInspectionDetail.inspectionInfo.status.eq(ReviewStatus.NOT_CHECK));
        //定时任务ID
        if (null != request.getTaskId()) {
            builder.and(qInspectionDetail.taskInfo.id.eq(request.getTaskId()));
        }
        //定时任务质检结果批次
        if (StringUtils.isNotBlank(request.getTaskBatch())) {
            builder.and(qInspectionDetail.inspectionInfo.inspectionBatch.eq(request.getTaskBatch()));
        }
        //客服编号
        if (StringUtils.isNotBlank(request.getServiceCode())) {
            builder.and(qInspectionDetail.serviceCode.eq(request.getServiceCode()));
        }
        Iterator<InspectionDetail> inspectionDetailIterator = inspectionDetailRepository.findAll(builder).iterator();
        HashSet<InspectionDetail> inspectionDetailHashSet = Sets.newHashSet(inspectionDetailIterator);
        return inspectionDetailHashSet;
    }



    /**
     * 分页查询复核任务数据
     *
     * @param request
     * @return
     */
    public Page<ReviewTaskResponse> fetchPage(ReviewTaskRequest request, Pageable pageable, SessionModel sessionModel) {
        BooleanBuilder builder = new BooleanBuilder();
        QReviewTask qReviewTask = QReviewTask.reviewTask;
        //复核任务批次
        if (StringUtils.isNotBlank(request.getReviewTaskBatch())) {
            builder.and(qReviewTask.reviewTaskBatch.like("%".concat(request.getReviewTaskBatch()).concat("%")));
        }
        //创建时间
        if (null != request.getCreateTimeS() && null != request.getCreateTimeE()) {
            builder.and(qReviewTask.createTime.between(request.getCreateTimeS(), request.getCreateTimeE()));
        }
        //任务状态
        if (request.getReviewTaskStatus() != null && !request.getReviewTaskStatus().equals(ReviewTaskStatus.ALL)) {
            builder.and(qReviewTask.reviewTaskStatus.eq(request.getReviewTaskStatus()));
        }
        builder.and(qReviewTask.operatorId.eq(sessionModel.getUserId()));
        Page<ReviewTask> reviewTaskPage = reviewTaskRepository.findAll(builder, pageable);
        Page<ReviewTaskResponse> reviewTaskResponsePage = reviewTaskPage.map(reviewTask -> {
            ReviewTaskResponse response = new ReviewTaskResponse();
            BeanUtils.copyProperties(reviewTask, response);
            BigDecimal reviewTaskFinishNum = new BigDecimal(reviewTask.getReviewTaskFinishNum());
            if (reviewTask.getReviewTaskNum() == 0) {
                response.setFinishNum(new BigDecimal(0));
            } else {
                BigDecimal reviewTaskNum = new BigDecimal(reviewTask.getReviewTaskNum());
                response.setFinishNum(reviewTaskFinishNum.divide(reviewTaskNum, 4, BigDecimal.ROUND_HALF_UP));
            }
            return response;
        });
        return reviewTaskResponsePage;
    }

    /**
     * 根据ID查询复核人的详情中的基本信息
     * @param id
     * @return
     */
    public ReviewTaskResponse fetchById(Long id) {
        ReviewTask reviewTask = reviewTaskRepository.findById(id).orElseThrow(() -> new BadRequestException("", "没有当前需要查询的复核任务数据"));
        ReviewTaskResponse response = new ReviewTaskResponse();
        BeanUtils.copyProperties(reviewTask, response);
        if (null != reviewTask.getTaskId()) {
            TaskInfo taskInfo = taskInfoRepository.findById(reviewTask.getTaskId()).orElseThrow(() -> new BadRequestException("", "没有查询到对应的定时任务"));
            response.setTaskInfo(taskInfo);
        } else {
            response.setTaskInfo(new TaskInfo());
        }
        BigDecimal reviewTaskFinishNum = new BigDecimal(reviewTask.getReviewTaskFinishNum());
        if (reviewTask.getReviewTaskNum() == 0) {
            response.setFinishNum(new BigDecimal(0));
        } else {
            BigDecimal reviewTaskNum = new BigDecimal(reviewTask.getReviewTaskNum());
            response.setFinishNum(reviewTaskFinishNum.divide(reviewTaskNum, 4, BigDecimal.ROUND_HALF_UP));
        }

        return response;
    }

    /**
     * 根据ID查询复核人的详情中的明细信息（分页）
     * @param request 复核任务详情展示中，明细的查询request
     * @return
     */
    public Page<InspectionDetailQueryResponse> fetchByIdToDetailPage(ReviewTaskToDetailRequest request, Pageable pageable) {
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        QInspectionDetail qInspectionDetail = QInspectionDetail.inspectionDetail;
        //条件
        booleanBuilder.and(qInspectionDetail.reviewTask.id.eq(request.getId()));
        //客服编号
        if (StringUtils.isNotBlank(request.getServiceCode())) {
            booleanBuilder.and(qInspectionDetail.serviceCode.eq(request.getServiceCode()));
        }
        //部门
        if (null != request.getDeptId()) {
            booleanBuilder.and(qInspectionDetail.department.id.eq(request.getDeptId()));
        }
        //任务名称
        if (StringUtils.isNotBlank(request.getTaskName())) {
            booleanBuilder.and(qInspectionDetail.taskInfo.name.like("%".concat(request.getTaskName()).concat("%")));
        }
        //命中规则
        if (StringUtils.isNotBlank(request.getRuleInfoName())) {
            booleanBuilder.and(qInspectionDetail.hitRule.contains(request.getRuleInfoName()));
        }
        //复核状态
        if (null != request.getReviewStatus()) {
            booleanBuilder.and(qInspectionDetail.reviewStatus.eq(request.getReviewStatus()));
        }

        Page<InspectionDetail> inspectionDetailPage = inspectionDetailRepository.findAll(booleanBuilder, pageable);
        Page<InspectionDetailQueryResponse> inspectionDetailResponse = inspectionDetailPage.map(obj -> {
            InspectionDetailQueryResponse response = new InspectionDetailQueryResponse();
            BeanUtils.copyProperties(obj, response);
            DepartmentResponse deptResponse = new DepartmentResponse();
            if (!Objects.isNull(obj.getDepartment())) {
                BeanUtils.copyProperties(obj.getDepartment(), deptResponse);
            }
            response.setDepartment(deptResponse);
            return response;
        });
        return inspectionDetailResponse;
    }

}
